from datetime import datetime, timedelta
import win32com.client as win32
import os


def get_date_str(delta=0):
    """
    获取日期字符串。
    参数:
    delta (int): 日期偏移量。默认为0。
    返回:
    str: 日期字符串。
    """
    return (datetime.now() + timedelta(days=delta)).strftime("%Y.%m.%d")


def get_app_book(file_path, show_app=False):
    """
    打开并返回指定路径的Excel工作簿对象。
    参数:
    file_path (str): Excel文件的路径。
    show_app (bool): 是否以调试模式启动Excel应用程序。默认为False。
    返回:
    wb: 如果成功打开工作簿，返回工作簿对象；否则返回None。
    异常:
    Exception: 如果打开工作簿失败，将捕获异常并打印错误信息。
    """

    # 启动Excel应用程序
    excel_app = win32.Dispatch("Excel.Application")
    # 设置是否可见, debug为True时可见
    excel_app.Visible = show_app
    # 尝试打开工作簿
    try:
        wb = excel_app.Workbooks.Open(os.path.abspath(file_path))
        return (wb, excel_app)
    except Exception as e:
        print(f"\033[31m打开工作簿失败: {e}, 脚本已停止\033[0m")
        excel_app.Quit()
        return None, None


def get_wb_infosheet(wb, sheet_name="info"):
    """
    获取指定工作表的信息。
    参数:
    wb: 工作簿对象。
    sheet_name (str): 工作表名称。默认为"info"。
    返回:
    sheet: 如果成功获取工作表，返回工作表对象；否则返回None。
    """
    try:
        sheet = wb.Worksheets(sheet_name)
        return sheet
    except Exception as e:
        print(f"\033[31m获取info工作表失败: {e}, 脚本已停止\033[0m")
        return None


def get_info(wb, sheet_name="info"):
    info_sheet = wb.Sheets(sheet_name)
    if info_sheet is None:
        print("\033[31m获取info工作表失败, 脚本已停止\033[0m")
        return None, None, None

    # info sheet定义了该wb的基本信息，
    # A列为日期预留列，B列以后为数据列
    # 其中type可选值为：dr(日报)，bt(节拍)，an(异常)，vs(车型统计)，pl(计划),ot(其他)
    # father_plan仅对type为dr类型有效，表示该日报所属的计划
    # name、type、father_plan为必需列，缺失任意一列将导致脚本停止
    used_rows = info_sheet.UsedRange.Rows.Count
    used_cols = info_sheet.UsedRange.Columns.Count
    date_cell = None
    # 将A列的第一个非空单元格作为日期单元格
    for row_idx in range(1, used_rows + 1):
        if info_sheet.Cells(row_idx, 1).Value is not None:
            date_cell = info_sheet.Cells(row_idx, 1)
            break

    # 获取name属性列索引
    name_col = -1
    # 截取第一行除第一个单元格外的所有单元格作为keys
    keys = [info_sheet.Cells(1, col).Value for col in range(2, used_cols + 1)]
    print(keys)
    try:
        name_col = keys.index("name") + 2
    except ValueError:
        pass
    if name_col == -1:
        print("\033[31m未找到name列\033[0m")
        return None, None, None

    info_data = {}
    for row_idx in range(2, used_rows + 1):
        name = info_sheet.Cells(row_idx, name_col).Value
        if name is None:
            continue
        # 以keys中所有不为"name"的列为键值对
        info_data[name] = {
            keys[col - 2]: info_sheet.Cells(row_idx, col).Value
            for col in range(2, used_cols + 1)
            if (keys[col - 2] != "name" and keys[col - 2] is not None)
        }

    return date_cell, info_data


def save_wb(wb, file_name, excel_app, close_app=False):
    """
    保存工作簿。
    参数:
    wb: 工作簿对象。
    file_name (str): 保存文件名。
    excel_app: Excel应用程序对象。
    close_app (bool): 是否关闭Excel应用程序。默认为False。
    """
    try:
        wb.Close(SaveChanges=True)
        print(f"保存成功: {file_name}")
    except Exception as e:
        print(f"\033[31m保存失败: {e}\033[0m")
    finally:
        if close_app:
            excel_app.Quit()


def t():
    print(get_date_str())
    print(get_date_str(1))
    print(get_date_str(-1))
    print(get_date_str(-365))


if __name__ == "__main__":
    t()
